package edu.gatech.cc.hwa.server.security.encryption;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import edu.gatech.cc.hwa.server.security.exceptions.HwaSecurityException;

public class Encryptor {
	
	private static Cipher cipher; 
	private static Map<String, SecretKeySpec> keys = new HashMap<String, SecretKeySpec>();
	private static SecretKeySpec secretKeySpec;
	
	public static byte[] decryptByteArray(byte[] cipherText, String key) throws HwaSecurityException {
		initEncryptor(key);
		return convertByteArray(cipherText, Cipher.DECRYPT_MODE);
	}
	
	public static byte[] encryptByteArray(byte[] plainText, String key) throws HwaSecurityException {
		initEncryptor(key);
		return convertByteArray(plainText, Cipher.ENCRYPT_MODE);
	}
	
	private static byte[] convertByteArray(byte[] inBytes, int mode) throws HwaSecurityException {
		try {
			cipher.init(mode, secretKeySpec);
			return cipher.doFinal(inBytes);
		} catch (InvalidKeyException e) {
			throw new HwaSecurityException(e);
		} catch (IllegalBlockSizeException e) {
			throw new HwaSecurityException(e);
		} catch (BadPaddingException e) {
			throw new HwaSecurityException(e);
		}
	}

	private static void initCipher() throws HwaSecurityException {
		try {
			cipher = Cipher.getInstance(EncryptionSettings.ENCRYPTION_ALGORITHM_MODE_PADDING);
		} catch (NoSuchAlgorithmException e) {
			throw new HwaSecurityException(e);
		} catch (NoSuchPaddingException e) {
			throw new HwaSecurityException(e);
		}
	}
	
	private static void initEncryptor(String key) throws HwaSecurityException {
		initCipher();
		addKey(key);
	}
	
	private static void addKey(String key) throws HwaSecurityException {
		if (!keys.containsKey(key)) {
			keys.put(key, KeyConverter.stringToAesKey(key));
		}
		secretKeySpec = keys.get(key);
	}
	
	private Encryptor() {}
}
